home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 7 / Amiga Format AFCD07 (Dec 1996, Issue 91).iso / serious / shareware / programming / aros / dos / createnewproc.c < prev    next >
C/C++ Source or Header  |  1996-09-13  |  8KB  |  279 lines

  1. /*
  2.     (C) 1995-96 AROS - The Amiga Replacement OS
  3.     $Id: createnewproc.c,v 1.5 1996/09/13 17:50:05 digulla Exp $
  4.     $Log: createnewproc.c,v $
  5.     Revision 1.5  1996/09/13 17:50:05  digulla
  6.     Use IPTR
  7.  
  8.     Revision 1.4  1996/09/11 12:56:39  digulla
  9.     Bugfix and a lot of new checks by M. Fleischer
  10.  
  11.     Desc:
  12.     Lang: english
  13. */
  14. #include <exec/memory.h>
  15. #include <clib/exec_protos.h>
  16. #include <dos/dosextens.h>
  17. #include <dos/filesystem.h>
  18. #include <dos/dostags.h>
  19. #include <clib/dos_protos.h>
  20. #include <utility/tagitem.h>
  21. #include <clib/utility_protos.h>
  22. #include "dos_intern.h"
  23.  
  24. #define NEWLIST(l)                          \
  25. ((l)->lh_Head=(struct Node *)&(l)->lh_Tail, \
  26.  (l)->lh_Tail=NULL,                         \
  27.  (l)->lh_TailPred=(struct Node *)(l))
  28.  
  29. static void KillCurrentProcess(void);
  30. struct Process *AddProcess(struct Process *process, STRPTR argPtr,
  31. ULONG argSize, APTR initialPC, APTR finalPC, struct DosLibrary *DOSBase);
  32.  
  33. /*****************************************************************************
  34.  
  35.     NAME */
  36.     #include <clib/dos_protos.h>
  37.  
  38.     __AROS_LH1(struct Process *, CreateNewProc,
  39.  
  40. /*  SYNOPSIS */
  41.     __AROS_LHA(struct TagItem *, tags, D1),
  42.  
  43. /*  LOCATION */
  44.     struct DosLibrary *, DOSBase, 83, Dos)
  45.  
  46. /*  FUNCTION
  47.     Create a new process using the tagitem array.
  48.  
  49.     INPUTS
  50.     tags - information on the new process.
  51.  
  52.     RESULT
  53.     Pointer to the new process or NULL on error.
  54.  
  55.     NOTES
  56.  
  57.     EXAMPLE
  58.  
  59.     BUGS
  60.  
  61.     SEE ALSO
  62.  
  63.     INTERNALS
  64.  
  65.     HISTORY
  66.     29-10-95    digulla automatically created from
  67.                 dos_lib.fd and clib/dos_protos.h
  68.  
  69. *****************************************************************************/
  70. {
  71.     __AROS_FUNC_INIT
  72.     __AROS_BASE_EXT_DECL(struct DosLibrary *,DOSBase)
  73.  
  74.     /* Allocated resources */
  75.     struct Process *process=NULL;
  76.     BPTR input=0, output=0, curdir=0;
  77.     STRPTR stack=NULL, name=NULL, argptr=NULL;
  78.     ULONG namesize, argsize=0;
  79.     struct MemList *memlist=NULL;
  80.     struct CommandLineInterface *cli=NULL;
  81.  
  82.     struct Process *me=(struct Process *)FindTask(NULL);
  83.     STRPTR s;
  84.     BPTR *oldpath, *newpath, *nextpath;
  85.  
  86.     struct TagItem defaults[]=
  87.     {
  88.     { NP_Seglist, 0 },
  89.     { NP_Entry, (IPTR)NULL },
  90.     { NP_Input, ~0ul },
  91.     { NP_CloseInput, 1 },
  92.     { NP_Output, ~0ul },
  93.     { NP_CloseOutput, 1 },
  94.     { NP_Error, 0 },
  95.     { NP_CloseError, 1 },
  96.     { NP_CurrentDir, ~0ul },
  97.     { NP_StackSize, 4000 },
  98.     { NP_Name, (IPTR)"New Process" },
  99.     { NP_Priority, me->pr_Task.tc_Node.ln_Pri },
  100.     { NP_Arguments, (IPTR)NULL },
  101.     { NP_Cli, 0 },
  102.     { TAG_END, 0 }
  103.     };
  104.     /* C has no exceptions. This is a simple replacement. */
  105. #define ERROR_IF(a)  if(a) goto error  /* Throw a generic error. */
  106. #define ENOMEM_IF(a) if(a) goto enomem /* Throw out of memory. */
  107.  
  108.     ApplyTagChanges(defaults,tags);
  109.  
  110.     process=(struct Process *)AllocMem(sizeof(struct Process),MEMF_PUBLIC|MEMF_CLEAR);
  111.     ENOMEM_IF(process==NULL);
  112.     stack=AllocMem(defaults[9].ti_Data,MEMF_PUBLIC);
  113.     ENOMEM_IF(stack==NULL);
  114.     s=(STRPTR)defaults[10].ti_Data;
  115.     while(*s++)
  116.     ;
  117.     namesize=s-(STRPTR)defaults[10].ti_Data;
  118.     name=AllocMem(namesize,MEMF_PUBLIC);
  119.     ENOMEM_IF(name==NULL);
  120.     s=(STRPTR)defaults[12].ti_Data;
  121.     if(s!=NULL)
  122.     {
  123.     while(*s++)
  124.         ;
  125.     argsize=s-(STRPTR)defaults[12].ti_Data;
  126.     argptr=(STRPTR)AllocVec(argsize,MEMF_PUBLIC);
  127.     ENOMEM_IF(argptr==NULL);
  128.     }
  129.     memlist=AllocMem(sizeof(struct MemList)+2*sizeof(struct MemEntry),MEMF_ANY);
  130.     ENOMEM_IF(memlist==NULL);
  131.     if(defaults[13].ti_Data)
  132.     {
  133.     cli=(struct CommandLineInterface *)AllocDosObject(DOS_CLI,NULL);
  134.     ENOMEM_IF(cli==NULL);
  135.     oldpath=NULL;
  136.     if(me->pr_Task.tc_Node.ln_Type==NT_PROCESS)
  137.     {
  138.         struct CommandLineInterface *oldcli=Cli();
  139.         if(oldcli!=NULL)
  140.         oldpath=BADDR(oldcli->cli_CommandDir);
  141.     }
  142.     newpath=&cli->cli_CommandDir;
  143.     while(oldpath!=NULL)
  144.     {
  145.         nextpath=AllocVec(2*sizeof(BPTR),MEMF_CLEAR);
  146.         ENOMEM_IF(nextpath==NULL);
  147.         newpath[0]=MKBADDR(nextpath);
  148.         nextpath[1]=DupLock(oldpath[1]);
  149.         ERROR_IF(!nextpath[1]);
  150.         newpath=nextpath;
  151.         oldpath=BADDR(oldpath[0]);
  152.     }
  153.     }
  154.     if(defaults[2].ti_Data==~0ul)
  155.     {
  156.     input=Open("NIL:",MODE_OLDFILE);
  157.     ERROR_IF(!input);
  158.     defaults[2].ti_Data=input;
  159.     }
  160.     if(defaults[4].ti_Data==~0ul)
  161.     {
  162.     output=Open("NIL:",MODE_NEWFILE);
  163.     ERROR_IF(!output);
  164.     defaults[4].ti_Data=output;
  165.     }
  166.     if(defaults[8].ti_Data==~0ul)
  167.     {
  168.     if(me->pr_Task.tc_Node.ln_Type==NT_PROCESS)
  169.     {
  170.         curdir=Lock("",SHARED_LOCK);
  171.         ERROR_IF(!curdir);
  172.         defaults[8].ti_Data=curdir;
  173.     }else
  174.         defaults[8].ti_Data=0;
  175.     }
  176.  
  177.     CopyMem((APTR)defaults[10].ti_Data,name,namesize);
  178.     CopyMem((APTR)defaults[12].ti_Data,argptr,argsize);
  179.     process->pr_Task.tc_Node.ln_Type=NT_PROCESS;
  180.     process->pr_Task.tc_Node.ln_Name=name;
  181.     process->pr_Task.tc_Node.ln_Pri=defaults[11].ti_Data;
  182.     process->pr_Task.tc_SPLower=stack;
  183.     process->pr_Task.tc_SPUpper=stack+defaults[9].ti_Data;
  184.  
  185. /*  process->pr_ReturnAddr; */
  186.     NEWLIST(&process->pr_Task.tc_MemEntry);
  187.     memlist->ml_NumEntries=3;
  188.     memlist->ml_ME[0].me_Addr=process;
  189.     memlist->ml_ME[0].me_Length=sizeof(struct Process);
  190.     memlist->ml_ME[1].me_Addr=stack;
  191.     memlist->ml_ME[1].me_Length=defaults[9].ti_Data;
  192.     memlist->ml_ME[2].me_Addr=name;
  193.     memlist->ml_ME[2].me_Length=namesize;
  194.     AddHead(&process->pr_Task.tc_MemEntry,&memlist->ml_Node);
  195.     process->pr_MsgPort.mp_Node.ln_Type=NT_MSGPORT;
  196.     process->pr_MsgPort.mp_Flags=PA_SIGNAL;
  197.     process->pr_MsgPort.mp_SigBit=SIGB_DOS;
  198.     process->pr_MsgPort.mp_SigTask=process;
  199.     NEWLIST(&process->pr_MsgPort.mp_MsgList);
  200.     process->pr_SegList=defaults[0].ti_Data;
  201.     process->pr_StackSize=defaults[9].ti_Data;
  202.     process->pr_GlobVec=NULL;
  203.     Forbid();
  204.     process->pr_TaskNum=DOSBase->dl_ProcCnt++;
  205.     Permit();
  206.     process->pr_StackBase=(IPTR)process->pr_Task.tc_SPUpper;
  207.     process->pr_Result2=0;
  208.     process->pr_CurrentDir=defaults[8].ti_Data;
  209.     process->pr_CIS=defaults[2].ti_Data;
  210.     process->pr_COS=defaults[4].ti_Data;
  211.     process->pr_CES=defaults[6].ti_Data;
  212. /*  process->pr_ConsoleTask=; */
  213. /*  process->pr_FileSystemTask=; */
  214.     process->pr_CLI=MKBADDR(cli);
  215. /*  process->pr_PktWait=; */
  216. /*  process->pr_WindowPtr=; */
  217. /*  process->pr_HomeDir=; */
  218.     process->pr_Flags=(defaults[3].ti_Data?PRF_CLOSEINPUT:0)|
  219.               (defaults[5].ti_Data?PRF_CLOSEOUTPUT:0)|
  220.               (defaults[7].ti_Data?PRF_CLOSEERROR:0)|
  221.               (defaults[13].ti_Data?PRF_FREECLI:0)|
  222.               PRF_FREEARGS|PRF_FREESEGLIST|PRF_FREECURRDIR;
  223. /*  process->pr_ExitCode=; */
  224. /*  process->pr_ExitData=; */
  225.     process->pr_Arguments=argptr;
  226.     NEWLIST((struct List *)&process->pr_LocalVars);
  227.     process->pr_ShellPrivate=0;
  228.  
  229.     if(AddProcess(process,argptr,argsize,defaults[0].ti_Data?
  230.           (APTR)BADDR(defaults[0].ti_Data+1):
  231.           (APTR)defaults[1].ti_Data,KillCurrentProcess,
  232.           DOSBase)!=NULL)
  233.     return process;
  234.  
  235.     /* Fall through */
  236. enomem:
  237.     if(me->pr_Task.tc_Node.ln_Type==NT_PROCESS)
  238.     me->pr_Result2=ERROR_NO_FREE_STORE;
  239. error:
  240.     FreeDosObject(DOS_CLI,cli);
  241.     UnLock(curdir);
  242.     Close(output);
  243.     Close(input);
  244.     FreeVec(argptr);
  245.     if(memlist!=NULL)
  246.     FreeMem(memlist,sizeof(struct MemList)+2*sizeof(struct MemEntry));
  247.     if(name!=NULL)
  248.     FreeMem(name,namesize);
  249.     if(stack!=NULL)
  250.     FreeMem(stack,defaults[9].ti_Data);
  251.     if(process!=NULL)
  252.     FreeMem(process,sizeof(struct Process));
  253.     return NULL;
  254.     __AROS_FUNC_EXIT
  255. } /* CreateNewProc */
  256.  
  257. static void KillCurrentProcess(void)
  258. {
  259.     /* I need the global here because there is no local way to get it */
  260.     extern struct DosLibrary *DOSBase;
  261.     struct Process *me=(struct Process *)FindTask(NULL);
  262.  
  263.     if(me->pr_Flags&PRF_CLOSEINPUT)
  264.     Close(me->pr_CIS);
  265.     if(me->pr_Flags&PRF_CLOSEOUTPUT)
  266.     Close(me->pr_COS);
  267.     if(me->pr_Flags&PRF_CLOSEERROR)
  268.     Close(me->pr_CES);
  269.     if(me->pr_Flags&PRF_FREEARGS)
  270.     FreeVec(me->pr_Arguments);
  271.     if(me->pr_Flags&PRF_FREESEGLIST)
  272.     UnLoadSeg(me->pr_SegList);
  273.     if(me->pr_Flags&PRF_FREECURRDIR)
  274.     UnLock(me->pr_CurrentDir);
  275.     if(me->pr_Flags&PRF_FREECLI)
  276.     FreeDosObject(DOS_CLI,BADDR(me->pr_CLI));
  277.     RemTask(NULL);
  278. }
  279.